package main

import (
	"fmt"
	"gitee.com/wayjin/fabric-extension/cryptoutil"
	"gitee.com/wayjin/fabric-extension/cryptoutil/caclient"
	"gitee.com/wayjin/fabric-extension/gateway"
	"github.com/spf13/cobra"
	"io/ioutil"
	"log"
)

func status(cmd *cobra.Command, args []string) {
	if peerAddress == "" {
		log.Fatal("peerAddress is required")
	}
	w, err := getCardFromFile(cardName)
	if err != nil {
		log.Fatal(err)
	}
	peerCtx := gateway.PeerContext{
		Host:peerAddress,
		ServiceName:serviceName,
		RootTLSCert:w,
	}
	crypto, err := cryptoutil.GetMyCryptoSuiteFromBytes(w.GetCert(), w.GetKey(), nil, mspid)
	if err != nil {
		log.Fatal("invalid cryptocert: ", err)
	}
	peerStatue, err := gateway.GetPeerStatus(crypto, peerCtx)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println("status:", peerStatue)
}

func channelCreate(cmd *cobra.Command, args []string) {
	if peerAddress == "" {
		log.Fatal("peerAddress is required")
	}
	if ordererAddress == "" {
		log.Fatal("ordererAddress is required")
	}
	crypto, err := cryptoutil.GetMyCryptoSuiteFromFile(userCert, userKey, mspid, nil)
	if err != nil {
		log.Fatal(err)
	}
	ordererCtx := gateway.OrdererContext{
		Host:        ordererAddress,
		ServiceName: "",
		RootTLSCert: nil,
	}
	err = gateway.CreateChannel(crypto, "", "", ordererCtx)
	if err != nil {
		log.Fatal("create channel fail:", err)
	}
	fmt.Println("create channel success.")
}

func channelJoin(cmd *cobra.Command, args []string) {
	if peerAddress == "" {
		log.Fatal("peerAddress is required")
	}

	crypto, err := cryptoutil.GetMyCryptoSuiteFromFile(userCert, userKey, mspid, nil)
	if err != nil {
		log.Fatal("fail to get cryptosuite: ", err)
	}
	ordererCtx := gateway.OrdererContext{}
	peerCtx := []gateway.PeerContext{}
	gateway.JoinChannel(crypto, ordererCtx, peerCtx, "mychannel")
}

func getCardFromFile(cardName string) (caclient.Wallet, error) {
	data, err := ioutil.ReadFile(cardName)
	if err != nil {
		return nil, err
	}

	return  caclient.DecodeWallet(data)
}

type tlsCert struct {
	file string
}

func (cert tlsCert) GetTlsCert() []byte {
	data, err := ioutil.ReadFile(cert.file)
	if err != nil {
		panic(err)
	}
	return data
}

func channelList(cmd *cobra.Command, args []string) {
	var (
		crypto cryptoutil.CryptoSuite
		err error
		peerCtx gateway.PeerContext
	)
	if cardName != "" {
		w, err := getCardFromFile(cardName)
		if err != nil {
			log.Fatal(err)
		}

		crypto, err = cryptoutil.GetMyCryptoSuiteFromBytes(w.GetTlsCert(), w.GetKey(), nil, mspid)
		if err != nil {
			log.Fatal("fail to get cryptosuite: ", err)
		}
		peerCtx = gateway.PeerContext{
			Host:        peerAddress,
			ServiceName: serviceName,
			RootTLSCert: w,
		}
	} else {
		crypto, err = cryptoutil.GetMyCryptoSuiteFromFile(userCert, userKey, mspid, nil )
		if err != nil {
			log.Fatal(err)
		}
		peerCtx = gateway.PeerContext{
			Host: peerAddress,
			ServiceName:serviceName,
			RootTLSCert:tlsCert{file:tlsCaCert},
		}
	}

	channels, err := gateway.ListChannels(crypto, peerCtx)
	if err != nil {
		log.Fatal("list channel fail:", err)
	}
	fmt.Println("channels:", channels)
}

func createUser(cmd *cobra.Command, args []string) {
	if userName == "" {
		log.Fatal("username is required")
	}
	if userSecret == "" {
		log.Fatal("user secret is required")
	}
	if caURL == "" {
		log.Fatal("url of CA is required")
	}

	var auth cryptoutil.KeyStore
	var err error
	if adminCert != "" && adminKey != "" {
		auth, err = cryptoutil.LoadKeyStoreFromFile(adminCert, adminKey, nil)
		if err != nil {
			log.Fatal(err)
		}
	}
	client, err := caclient.NewClient2(caURL)
	if err != nil {
		log.Fatal(err)
	}
	req := caclient.NewRegisterRequest(userName, userSecret, affiliation, caclient.ID_USER)
	idcert, err := client.GetIdentityCryptoCerts(req, auth, false)
	if err != nil {
		log.Fatal(err)
	}
	wallet, err := idcert.Wallet()
	if err != nil {
		log.Fatal(err)
	}
	data, err := wallet.Marshal(nil)
	if err != nil {
		log.Fatal(err)
	}
	ioutil.WriteFile(userName+".card", data, 0644)
}